home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2018 January / PCgo 01-2018 CD-ROM Germany.iso / nw.pak / Unnamed File 000143.txt < prev    next >
Encoding:
Text File  |  2015-07-29  |  7.7 KB  |  248 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. /**
  6.  * @fileoverview This file provides utility functions for position popups.
  7.  */
  8.  
  9. cr.exportPath('cr.ui');
  10.  
  11. /**
  12.  * Type def for rects as returned by getBoundingClientRect.
  13.  * @typedef {{left: number, top: number, width: number, height: number,
  14.  *            right: number, bottom: number}}
  15.  */
  16. cr.ui.Rect;
  17.  
  18. /**
  19.  * Enum for defining how to anchor a popup to an anchor element.
  20.  * @enum {number}
  21.  */
  22. cr.ui.AnchorType = {
  23.   /**
  24.    * The popup's right edge is aligned with the left edge of the anchor.
  25.    * The popup's top edge is aligned with the top edge of the anchor.
  26.    */
  27.   BEFORE: 1,  // p: right, a: left, p: top, a: top
  28.  
  29.   /**
  30.    * The popop's left edge is aligned with the right edge of the anchor.
  31.    * The popup's top edge is aligned with the top edge of the anchor.
  32.    */
  33.   AFTER: 2,  // p: left a: right, p: top, a: top
  34.  
  35.   /**
  36.    * The popop's bottom edge is aligned with the top edge of the anchor.
  37.    * The popup's left edge is aligned with the left edge of the anchor.
  38.    */
  39.   ABOVE: 3,  // p: bottom, a: top, p: left, a: left
  40.  
  41.   /**
  42.    * The popop's top edge is aligned with the bottom edge of the anchor.
  43.    * The popup's left edge is aligned with the left edge of the anchor.
  44.    */
  45.   BELOW: 4  // p: top, a: bottom, p: left, a: left
  46. };
  47.  
  48. cr.define('cr.ui', function() {
  49.   /** @const */
  50.   var AnchorType = cr.ui.AnchorType;
  51.  
  52.   /**
  53.    * Helper function for positionPopupAroundElement and positionPopupAroundRect.
  54.    * @param {!cr.ui.Rect} anchorRect The rect for the anchor.
  55.    * @param {!HTMLElement} popupElement The element used for the popup.
  56.    * @param {cr.ui.AnchorType} type The type of anchoring to do.
  57.    * @param {boolean=} opt_invertLeftRight Whether to invert the right/left
  58.    *     alignment.
  59.    */
  60.   function positionPopupAroundRect(anchorRect, popupElement, type,
  61.                                    opt_invertLeftRight) {
  62.     var popupRect = popupElement.getBoundingClientRect();
  63.     var availRect;
  64.     var ownerDoc = popupElement.ownerDocument;
  65.     var cs = ownerDoc.defaultView.getComputedStyle(popupElement);
  66.     var docElement = ownerDoc.documentElement;
  67.  
  68.     if (cs.position == 'fixed') {
  69.       // For 'fixed' positioned popups, the available rectangle should be based
  70.       // on the viewport rather than the document.
  71.       availRect = {
  72.         height: docElement.clientHeight,
  73.         width: docElement.clientWidth,
  74.         top: 0,
  75.         bottom: docElement.clientHeight,
  76.         left: 0,
  77.         right: docElement.clientWidth
  78.       };
  79.     } else {
  80.       availRect = popupElement.offsetParent.getBoundingClientRect();
  81.     }
  82.  
  83.     if (cs.direction == 'rtl')
  84.       opt_invertLeftRight = !opt_invertLeftRight;
  85.  
  86.     // Flip BEFORE, AFTER based on alignment.
  87.     if (opt_invertLeftRight) {
  88.       if (type == AnchorType.BEFORE)
  89.         type = AnchorType.AFTER;
  90.       else if (type == AnchorType.AFTER)
  91.         type = AnchorType.BEFORE;
  92.     }
  93.  
  94.     // Flip type based on available size
  95.     switch (type) {
  96.       case AnchorType.BELOW:
  97.         if (anchorRect.bottom + popupRect.height > availRect.height &&
  98.             popupRect.height <= anchorRect.top) {
  99.           type = AnchorType.ABOVE;
  100.         }
  101.         break;
  102.       case AnchorType.ABOVE:
  103.         if (popupRect.height > anchorRect.top &&
  104.             anchorRect.bottom + popupRect.height <= availRect.height) {
  105.           type = AnchorType.BELOW;
  106.         }
  107.         break;
  108.       case AnchorType.AFTER:
  109.         if (anchorRect.right + popupRect.width > availRect.width &&
  110.             popupRect.width <= anchorRect.left) {
  111.           type = AnchorType.BEFORE;
  112.         }
  113.         break;
  114.       case AnchorType.BEFORE:
  115.         if (popupRect.width > anchorRect.left &&
  116.             anchorRect.right + popupRect.width <= availRect.width) {
  117.           type = AnchorType.AFTER;
  118.         }
  119.         break;
  120.     }
  121.     // flipping done
  122.  
  123.     var style = popupElement.style;
  124.     // Reset all directions.
  125.     style.left = style.right = style.top = style.bottom = 'auto';
  126.  
  127.     // Primary direction
  128.     switch (type) {
  129.       case AnchorType.BELOW:
  130.         if (anchorRect.bottom + popupRect.height <= availRect.height)
  131.           style.top = anchorRect.bottom + 'px';
  132.         else
  133.           style.bottom = '0';
  134.         break;
  135.       case AnchorType.ABOVE:
  136.         if (availRect.height - anchorRect.top >= 0)
  137.           style.bottom = availRect.height - anchorRect.top + 'px';
  138.         else
  139.           style.top = '0';
  140.         break;
  141.       case AnchorType.AFTER:
  142.         if (anchorRect.right + popupRect.width <= availRect.width)
  143.           style.left = anchorRect.right + 'px';
  144.         else
  145.           style.right = '0';
  146.         break;
  147.       case AnchorType.BEFORE:
  148.         if (availRect.width - anchorRect.left >= 0)
  149.           style.right = availRect.width - anchorRect.left + 'px';
  150.         else
  151.           style.left = '0';
  152.         break;
  153.     }
  154.  
  155.     // Secondary direction
  156.     switch (type) {
  157.       case AnchorType.BELOW:
  158.       case AnchorType.ABOVE:
  159.         if (opt_invertLeftRight) {
  160.           // align right edges
  161.           if (anchorRect.right - popupRect.width >= 0) {
  162.             style.right = availRect.width - anchorRect.right + 'px';
  163.  
  164.           // align left edges
  165.           } else if (anchorRect.left + popupRect.width <= availRect.width) {
  166.             style.left = anchorRect.left + 'px';
  167.  
  168.           // not enough room on either side
  169.           } else {
  170.             style.right = '0';
  171.           }
  172.         } else {
  173.           // align left edges
  174.           if (anchorRect.left + popupRect.width <= availRect.width) {
  175.             style.left = anchorRect.left + 'px';
  176.  
  177.           // align right edges
  178.           } else if (anchorRect.right - popupRect.width >= 0) {
  179.             style.right = availRect.width - anchorRect.right + 'px';
  180.  
  181.           // not enough room on either side
  182.           } else {
  183.             style.left = '0';
  184.           }
  185.         }
  186.         break;
  187.  
  188.       case AnchorType.AFTER:
  189.       case AnchorType.BEFORE:
  190.         // align top edges
  191.         if (anchorRect.top + popupRect.height <= availRect.height) {
  192.           style.top = anchorRect.top + 'px';
  193.  
  194.         // align bottom edges
  195.         } else if (anchorRect.bottom - popupRect.height >= 0) {
  196.           style.bottom = availRect.height - anchorRect.bottom + 'px';
  197.  
  198.           // not enough room on either side
  199.         } else {
  200.           style.top = '0';
  201.         }
  202.         break;
  203.     }
  204.   }
  205.  
  206.   /**
  207.    * Positions a popup element relative to an anchor element. The popup element
  208.    * should have position set to absolute and it should be a child of the body
  209.    * element.
  210.    * @param {!HTMLElement} anchorElement The element that the popup is anchored
  211.    *     to.
  212.    * @param {!HTMLElement} popupElement The popup element we are positioning.
  213.    * @param {cr.ui.AnchorType} type The type of anchoring we want.
  214.    * @param {boolean=} opt_invertLeftRight Whether to invert the right/left
  215.    *     alignment.
  216.    */
  217.   function positionPopupAroundElement(anchorElement, popupElement, type,
  218.                                       opt_invertLeftRight) {
  219.     var anchorRect = anchorElement.getBoundingClientRect();
  220.     positionPopupAroundRect(anchorRect, popupElement, type,
  221.                             !!opt_invertLeftRight);
  222.   }
  223.  
  224.   /**
  225.    * Positions a popup around a point.
  226.    * @param {number} x The client x position.
  227.    * @param {number} y The client y position.
  228.    * @param {!HTMLElement} popupElement The popup element we are positioning.
  229.    */
  230.   function positionPopupAtPoint(x, y, popupElement) {
  231.     var rect = {
  232.       left: x,
  233.       top: y,
  234.       width: 0,
  235.       height: 0,
  236.       right: x,
  237.       bottom: y
  238.     };
  239.     positionPopupAroundRect(rect, popupElement, AnchorType.BELOW);
  240.   }
  241.  
  242.   // Export
  243.   return {
  244.     positionPopupAroundElement: positionPopupAroundElement,
  245.     positionPopupAtPoint: positionPopupAtPoint
  246.   };
  247. });
  248.